// Author : Zhuowen Tu


#ifndef _MCMC_PARTICLE_H
#define _MCMC_PARTICLE_H

#include "mcRandVector.h"
#include "mcRasterColor.h"
#include "mcmcGibbsLearning.h"
#include "mcmcImageFilters.h"

#define	  LUV_COLOR_MODEL

/////////////////////////////////////////////////////////////////
class MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle();
	~MCMC_Particle();

	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL)=0;
	virtual void			Free();
	virtual int				Num(int isubpar=0){return num_particle;};
	virtual int				ChooseParticle(mcmcVector<float> &votes);
	virtual void			AddClusterVote(mcmcVector<float> &vc_vote, const int j, const int i, const int isubpar=0);

	virtual mcmcVector<double>	GetMean(const int iparticle)=0;
	virtual double			GetPdf(mcmcVector<float> &votes, mcmcVector<double> &means);
	virtual int				ClosestParticle(mcmcVector<double> &mx_mean)=0;
	virtual int				CloserParticle(const mcmcVector<double> &mx_mean1, const mcmcVector<double> &mx_mean2, const int ipar)=0;
	virtual void			Diffuse(mcmcVector<double> &mx_mean, const int ipar)=0;
	virtual int				SelectModelType(mcmcMatrix<int> &mx_label, const int nlabel, irmm_Rect &bound){return 0;};
	virtual double			DistanceBtwnParticles(const int ipar1, const int ipar2){return 0.0;};
	mcmcMatrix<float>			*pmx_saliency_map;
	mcmcMatrix<int>				mx_map_temp;
	MCMC_FilterResp			 *prespFilters;

protected:
	int						num_particle;
	RF						rf_model;
};


/////////////////////////////////////////////////////////////////
class MCMC_Particle_LUV : public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_LUV();
	~MCMC_Particle_LUV();
	void Free(void);

	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &vc_mean);
	virtual int				CloserParticle(const mcmcVector<double> &vc_mean1, const mcmcVector<double> &vc_mean2, const int ipar);
	virtual void			Diffuse(mcmcVector<double> &vc_mean, const int ipar);

protected:
	mcmcVector<double>		*pmeans;			// particle centers in L,U,V space
	irmm_RandVector		*prand_vectors;
};


/////////////////////////////////////////////////////////////////
class MCMC_Particle_2DColor : public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_2DColor();
	~MCMC_Particle_2DColor();
	void Free(void);

	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &mx_N);
	virtual int				CloserParticle(const mcmcVector<double> &mx_N1, const mcmcVector<double> &mx_N2, const int ipar);
	virtual void			Diffuse(mcmcVector<double> &mx_mean, const int ipar);

protected:
	mcmcVector<double>		*pvc_N;		// normal direction of beta surface
};

/////////////////////////////////////////////////////////////////
class MCMC_Particle_3DColor : public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_3DColor();
	~MCMC_Particle_3DColor();
	void Free(void);

public:
	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &vc_mean);
	virtual int				CloserParticle(const mcmcVector<double> &vc_mean1, const mcmcVector<double> &vc_mean2, const int ipar);

protected:
	virtual	void			ComputeMeanIntensity(void);
	virtual void			EM(void);
	virtual void			Diffuse(mcmcVector<double> &vc_N_intensity, const int ipar);
	virtual double			DistanceToAParticle(mcmcVector<double> &vc_color, const int ipar);
			void			ToColor(const mcmcVector<double> &vc_N_intensity, mcmcVector<double> &vc_color);
private:
			void			PrecisionNormal(void);
			void			PrecisionIntensity(void);

protected:
	mcmcVector<double>	*pvc_N;		// normal direction of beta surface
	mcmcVector<double>	vc_meanintensity;	// intensity centers
};

/////////////////////////////////////////////////////////////////
// intensity particles
class MCMC_Particle_Intensity: public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_Intensity();
	~MCMC_Particle_Intensity();
	void Free(void);

public:
	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &vc_mean);
	virtual int				CloserParticle(const mcmcVector<double> &vc_mean1, const mcmcVector<double> &vc_mean2, const int ipar);

protected:
	virtual	void			ComputeMeanIntensity(void);
	virtual void			EM(void);
	virtual void			Diffuse(mcmcVector<double> &vc_intensity, const int ipar);
	virtual double			DistanceToAParticle(double intensity, const int ipar);
	virtual double			DistanceBtwnParticles(const int ipar1, const int ipar2){return DistanceToAParticle(vc_meanintensity(ipar1),ipar2);};

private:
			void			PrecisionIntensity(void);
protected:
	mcmcVector<double>			vc_meanintensity;	// intensity centers
};


double DistanceToA3DColorMode(mcmcVector<double> &vc_color, mcmcVector<double> &vc_N, const double intensity);


/////////////////////////////////////////////////////////////////
// 3d color model 2 : L, U, and V
class MCMC_Particle_3DColor2 : public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_3DColor2();
	~MCMC_Particle_3DColor2();
	void Free(void);

public:
	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &vc_luv);
	virtual int				CloserParticle(const mcmcVector<double> &mx_mean1, const mcmcVector<double> &mx_mean2, const int ipar){return 0;};
	virtual void			ToAColorImage(Raster_Color<uchar> &image_color);
	virtual void			Diffuse(mcmcVector<double> &vc_luv, const int ipar);
	// for Gauss in l and (u,v)
	virtual double			GetPdf(mcmcVector<float> &votes, mcmcVector<double> &vc_mean_luv);

protected:
	virtual	void			ComputeMean(void);
	virtual void			EM(void);
	virtual double			DistanceToAParticle(mcmcVector<double> &vc_luv, const int ipar);
protected:
	mcmcVector<double>			*pvc_luv;
};

/////////////////////////////////////////////////////////////////////////////////////////////
class MCMC_Histogram_Clusters
{
public:
	// construction & destruction;
    MCMC_Histogram_Clusters(Raster<double> &ras_resp, mcmcMatrix<int> &mx_clutering, const int k, const int wsize, const double d);
	MCMC_Histogram_Clusters();
	~MCMC_Histogram_Clusters();

	virtual void	Set(Raster<double> &ras_resp, mcmcMatrix<int> &mx_clutering, const int k, const int wsize, const double d,
						bool bPixelHistExist=false);
	virtual double	DistanceToPar(const int row_j, const int col_i, const int ipar);
	virtual void	ComputeMeanHist(SimpleMatrix<Histogram> &newmean, mcmcMatrix<int> &mx_clutering);
	virtual double	DistanceBetweenPars(const int i, const int j);
	virtual void	SaveToFile(char *pname);
	inline	double	Entropy(const int ipar){return mx_cluster_histogram(ipar).Entropy();};

public:
	SimpleMatrix<Histogram>	mx_cluster_histogram;
	SimpleMatrix<Histogram>	mx_pixel_histogram;

	Raster<double>			ras_fresp;
	double					min_bin,max_bin;
	int						wsize;
	int						kcluster;
	double					delta;
};

/////////////////////////////////////////////////////////////////////////////////////////////
class MCMC_Particle_Texture : public MCMC_Particle
{
public:
	// construction & destruction
	MCMC_Particle_Texture(const bool blearn);
	~MCMC_Particle_Texture();
	void Free(void);

	// operations
	virtual void			Set(MCMC_FilterResp &respFilters, mcmcMatrix<int> &clst, char *pfile_name=NULL);
	virtual void			EmSmt(void);
	virtual double			DistanceToPar(const int row_j, const int col_i, const int ipar);
	virtual	double			CombinedDist(const mcmcVector<double> &vc_dist);
	virtual void			SavePixelHistogram(const int row, const int col, char *pname);
	virtual void			CreateSoftClusteringMap(void);

	virtual mcmcVector<double>	GetMean(const int iparticle);
	virtual int				ClosestParticle(mcmcVector<double> &mx_mean);
	virtual int				CloserParticle(const mcmcVector<double> &mx_mean1, const mcmcVector<double> &mx_mean2, const int ipar);
	virtual void			Diffuse(mcmcVector<double> &mx_mean, const int ipar){;};
	virtual void			LearnPLE4Particles(char *pfile_name=NULL)=0;
	virtual void			ComputeJacobs(void)=0;

public:
	int						window_size;
	mcmcMatrix<double>			mx_jacobs;			// normalize l,u,and v with R,G,B
	mcmcMatrix<double>			*p_mx_energymap;
	SimpleMatrix<bool>		vc_valid_cluster;	// some clusters may not be valid for a texture color

protected:
	MCMC_Histogram_Clusters	*phist_clusters;
	mcmcVector<int>				mx_type_index;
	mcmcVector<double>			vc_weights;
	double					dist_to_merge;

protected:
	bool					bprint_histograms;
	bool					bto_learn_texture;
};

/////////////////////////////////////////////////////////////////////////////////////////////
class MCMC_Particle_ColorTexture : public MCMC_Particle_Texture
{
public:
	// construction & destruction
	MCMC_Particle_ColorTexture(const bool blearn);
	~MCMC_Particle_ColorTexture();
	void Free(void);

	// operations
	virtual void			LearnPLE4Particles(char *pfile_name=NULL);
	virtual void			ComputeJacobs(void);

public:
	Raster_Color<uchar>		*p_mx_syn;

protected:
	Gibbs_B					*pref_b_l,*pref_b_u,*pref_b_v;	// for reference only
};

/////////////////////////////////////////////////////////////////////////////////////////////
class MCMC_Particle_IntensityTexture : public MCMC_Particle_Texture
{
public:
	// construction & destruction
	MCMC_Particle_IntensityTexture(const bool blearn);
	~MCMC_Particle_IntensityTexture();
	void Free(void);

	// operations
	virtual void			LearnPLE4Particles(char *pfile_name=NULL);
	virtual void			ComputeJacobs(void){;};

public:
	Raster<uchar>			*p_mx_syn;

protected:
	Gibbs_B					*pref_b_it;			// for reference only
};


#endif
